package cn.toutatis.common.controllerDepand;

import cn.toutatis.common.config.PagingQuery;
import cn.toutatis.common.config.ResultCode;
import cn.toutatis.common.exception.ContinueTransactionException;
import cn.toutatis.common.result.Actions;
import cn.toutatis.common.result.Result;
import cn.toutatis.common.toolkit.ObjectToolkit;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

import javax.annotation.PostConstruct;
import java.lang.reflect.Field;
import java.util.*;

/**
 * @author Toutatis_Gc
 * @param <O> 实体类
 * @param <SERVICE>  继承了MP的service
 */
@Transactional(rollbackFor = Exception.class)
public class BaseControllerImpl<O extends EntityBasicAttribute<O>, SERVICE extends GService<O>> implements BaseController<O> {

    public Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    public SERVICE service;

    public CommonWrapper<O> commonWrapper = CommonWrapper.getInstance();

    public Result result = new Result(true);

    @Autowired(required = false)
    HashMap globalMap;

    @PostConstruct
    public void init(){

    }

    @Override
    @RequestMapping(value = "/getList",method = RequestMethod.POST)
    public Result getList(PagingQuery pagingQuery, O obj) {
        Page<O> page = service.getList(pagingQuery,obj);
        Map<String,Object> objectMap = new HashMap<>(2);
        objectMap.put("list",page.getRecords());
        objectMap.put("totalCount",page.getTotal());
        result.setContent(objectMap,Actions.SELECT);
        return result;
    }

    @Override
    @RequestMapping(value = "/getById",method = RequestMethod.POST)
    public Result getById(O entity) {
        if (entity == null){
            result.setMessage(ResultCode.NOT_HAVE_SELECT_DATA);
            return result;
        }
        QueryWrapper<O> oQueryWrapper = new QueryWrapper<>(entity);
        O one = service.getOne(oQueryWrapper);
        result.setContent(one,Actions.SELECT);
        return result;
    }

    @Override
    @RequestMapping(value = "/updateStatus",method = RequestMethod.POST)
    public Result updateStatus(O entity) {
        if (entity == null){
            result.setMessage(ResultCode.NOT_HAVE_SELECT_DATA);
            return result;
        }
        entity.setLastUpdateTime(new Date());
        boolean sign = service.updateById(entity);
        result.setSign(sign,Actions.UPDATE);
        return result;
    }

    @Override
    @RequestMapping(value = "/batchDeleteReal",method = RequestMethod.POST)
    public Result batchDeleteReal(@RequestBody List<O> entities ,@RequestParam(required = false, defaultValue = "id",value = "idType") String idType) {
        if (entities.size() == 0){
            result.setMessage(ResultCode.NOT_HAVE_SELECT_DATA);
            return result;
        }
        List<String> ids = new ArrayList<>();
        entities.forEach(item ->{
            Class<? extends EntityBasicAttribute> aClass = item.getClass();
            Field[] fields = aClass.getDeclaredFields();
            for (Field field : fields) {
                field.setAccessible(true);
                if (field.getName().equals(idType)){
                    try {
                        Object objectId = field.get(item);
                        if (objectId != null){
                            String id = String.valueOf(objectId);
                            ids.add(id);
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                        throw new ContinueTransactionException(e.getMessage()+"\r\n反射获取id类型失败,请检查实体类id主键name是否为id,如果为否,请求请传递idType参数.");
                    }
                    break;
                }
                field.setAccessible(false);
            }
        });
        if (ids.size() != 0){
            boolean sign = service.removeByIds(ids);
            result.setSign(sign,Actions.DELETE);
        }else {
            String info = "所选数据筛选数量为0";
            result.setMessage(info);
            logger.warn(info);
        }
        return result;
    }

    @Override
    @RequestMapping(value = "/tombstone",method = RequestMethod.POST)
    public Result tombstone(@RequestBody List<O> entities) {
        if (entities.size() == 0){
            result.setMessage(ResultCode.NOT_HAVE_SELECT_DATA);
            return result;
        }
        String closeSign = globalMap == null ? "SYS_CLOSE_0000" : (String) globalMap.get("closeSign");
        entities.forEach(item -> {
            item.setStatus(closeSign);
            item.setLastUpdateTime(new Date());
        });
        result.setSign(service.updateBatchById(entities),Actions.DELETE);
        return result;
    }

    @Override
    @RequestMapping(value = "/tombstoneOne",method = RequestMethod.POST)
    public Result tombstoneOne(O entity) {
        if (entity == null){
            result.setMessage(ResultCode.NOT_HAVE_SELECT_DATA);
            return result;
        }
        String closeSign = globalMap == null ? "SYS_CLOSE_0000" : (String) globalMap.get("closeSign");
        entity.setStatus(closeSign);
        entity.setLastUpdateTime(new Date());
        result.setSign(service.updateById(entity),Actions.DELETE);
        return result;
    }

    @Override
    @RequestMapping(value = "/saveRecord",method = RequestMethod.POST)
    public Result saveRecord(O entity) {
        if (entity == null){
            result.setMessage(ResultCode.NOT_HAVE_SELECT_DATA);
            return result;
        }
        if (entity.getCreateTime() == null){
            entity.setCreateTime(new Date());
        }
        if (entity.getLastUpdateTime() == null){
            entity.setLastUpdateTime(new Date());
        }
        if (entity.getStatus() == null){
            String normalSign = globalMap == null ? "SYS_OPEN_0000" : (String) globalMap.get("normalSign");
            entity.setStatus(normalSign);
        }
        boolean save = service.save(entity);
        result.setSign(save,Actions.INSERT);
        return result;
    }

    @Override
    @RequestMapping(value = "/search",method = RequestMethod.POST)
    public Result search(@RequestBody JSONObject object) {
        if (object == null){
            result.setMessage(ResultCode.NOT_HAVE_SELECT_DATA);
            return result;
        }
        Integer currentPage = Integer.parseInt(String.valueOf(object.remove("currentPage")))-1;
        Object pageSize = object.remove("pageSize");
        QueryWrapper<O> wrapper = new QueryWrapper<>();
        Object createStart = object.getDate("createStart");
        Object createEnd = object.getDate("createEnd");
        ObjectToolkit objectToolkit = ObjectToolkit.getInstance();
        if (objectToolkit.strNotBlankTrim(createStart) && objectToolkit.strNotBlankTrim(createEnd)){
            object.remove("createStart");
            object.remove("createEnd");
            wrapper.between("createTime",createStart,createEnd);
        }else if (objectToolkit.objectIsNull(createStart) && objectToolkit.objectIsNull(createEnd)){

        }else {
            result.setCode(ResultCode.MISSING_PARAMETER);
            result.setMessage("请完善日期选择");
            return result;
        }
        for (Map.Entry<String, Object> next : object.entrySet()) {
            String key = next.getKey();
            Object value = next.getValue();
            if (objectToolkit.strNotBlankTrim(value)) {
                wrapper.like(key, value);
            }
        }
        int count = service.count(wrapper);
        wrapper.last("limit "+currentPage+","+pageSize);
        List<O> list = service.list(wrapper);
        Map<String,Object> map = new HashMap<>();
        map.put("totalCount",count);
        map.put("list",list);
        result.setContent(map,Actions.SELECT);
        return result;
    }

}
